import { VNodeChild } from 'vue';
import type { ColumnProps } from 'ant-design-vue/lib/table';
import type { SortOrder } from 'ant-design-vue/lib/table/interface';
import { PaginationProps } from './pagination';
import { FormProps } from '@/basicComp/Form';
import { TableRowSelection } from './tableRowSelection';
import { SizeType } from './tableAction';
import { ComponentType } from './componentType';

// export declare type SortOrder = 'ascend' | 'descend';

export type CellFormat =
	| string
	| ((text: string, record: Recordable, index: number) => string | number)
	| Map<string | number, any>;

export interface BasicColumn extends ColumnProps {
	width?: string | number;
	children?: BasicColumn[];

	// 头部的提示文字
	helpMessage?: string | string[];

	flag?: 'INDEX' | 'DEFAULT' | 'CHECKBOX' | 'RADIO' | 'SWITCH' | 'ACTION';
	// 是否展示
	isShow?: boolean | ((column: BasicColumn) => boolean);
	// 默认是否展示，可通过改变column列显示
	defaultHidden?: boolean;
	// 权限编码控制是否显示
	auth?: string | string[];
	format?: CellFormat;

	customTitle?: VueNode;

	// 可编辑
	edit?: boolean;
	editRow?: boolean;
	editable?: boolean;
	editIcon?: boolean;
	editComponent?: ComponentType;
	editComponentProps?:
		| ((opt: {
				text: string | number | boolean | Recordable;
				record: Recordable;
				column: BasicColumn;
				index: number;
		  }) => Recordable)
		| Recordable;
	editRule?: boolean | ((text: string, record: Recordable) => Promise<string>);
	editValueMap?: (value: any) => string;
	onEditRow?: () => void;
	// 自定义修改后显示的内容
	editRender?: (opt: {
		text: string | number | boolean | Recordable;
		record: Recordable;
		column: BasicColumn;
		index: number;
	}) => VNodeChild | JSX.Element;
	// 动态 Disabled
	editDynamicDisabled?: boolean | ((record: Recordable) => boolean);
}

export interface ExpandedRowRenderRecord<T> extends TableCustomRecord<T> {
	indent?: number;
	expanded?: boolean;
}

export interface TableCustomRecord<T = Recordable> {
	record?: T;
	index?: number;
}

export interface FetchFieldSetting {
	// 请求接口当前页数字段
	pageField?: string;
	// 请求接口列表字段
	listField?: string;
	// 请求接口总页数字段
	pageSizeField?: string;
	// 请求接口总条数字段
	totalField?: string;
}

export interface SorterResult {
	column: ColumnProps;
	order: SortOrder;
	field: string;
	columnKey: string;
}
export interface FetchParams {
	// 后台接口中分页和关键字信息分开了，因此加上这个适应于本系统
	keyWordInfo?: Recordable;
	searchInfo?: Recordable;
	page?: number;
	sorterInfo?: Recordable;
	filterInfo?: Recordable;
}

export interface TableSetting {
	redo?: boolean;
	size?: boolean;
	setting?: boolean;
	fullScreen?: boolean;
}

export interface BasicTableProps<T = any> {
	// 表格help
	titleHelpMessage?: string | string[];
	// 自定义排序方法
	sorterFn?: (sortInfo: SorterResult) => any;
	// 筛选方法
	filterFn?: (data: Partial<Recordable<string[]>>) => any;
	columns: BasicColumn[];
	// 是否展示序号
	showIndexColumn?: boolean;
	indexColumnProps?: BasicColumn;
	// 操作
	actionColumn?: BasicColumn;
	// 请求接口
	api?: (...args: any) => Promise<any>;
	// 是否立即请求接口
	immediate?: boolean;
	// 接口配置字段
	fetchFieldsSetting?: Partial<FetchFieldSetting>;
	// 额外的搜索信息
	searchInfo?: Recordable;
	handleSearchInfoFn?: Fn;
	// 额外的关键字信息，由于后台关键字和分页分开传参，和searchinfo不同的是，该字段只会放入keyWordParam对象中
	keyWordInfo?: Recordable;
	handleKeyWordInfoFn?: Fn;
	// 是否开启loading
	loading?: boolean;
	// table row-key 若不提供，则自动创建uuid
	rowKey?: string | ((record: Recordable) => string);
	// 数据
	dataSource?: Recordable[];
	// 是否为树型表格
	isTreeTable?: boolean;
	// 超过长度是否省略
	ellipsis?: boolean;
	// 分页
	pagination?: PaginationProps | boolean;
	// 调用接口之前处理数据
	beforeFetch?: Fn;
	// 处理接口获取到的数据,只针对列表进行处理，而非后台返回的整个对象
	afterFetch?: Fn;
	// 显示表格设置
	tableSetting?: TableSetting;
	showTableSetting?: boolean;
	// 使用搜索表单
	useSearchForm?: boolean;
	formConfig?: Partial<FormProps>;
	resetWithTableSearchInfo?: boolean;
	// 是否自适应高度
	canResize?: boolean;
	// 表格滚动最大高度
	maxHeight?: number;
	// 是否继承父级高度（父级高度-表单高度-padding高度）
	isCanResizeParent?: boolean;
	// 自适应高度偏移， 计算结果-偏移量
	resizeHeightOffset?: number;
	// 是否自动生成key？若设置 rowKey: 'userId' 则不生效
	autoCreateKey?: boolean;
	// 在分页改变的时候清空选项
	clearSelectOnPageChange?: boolean;
	// 斑马纹
	striped?: boolean;

	/**
	 * antd table自带的属性
	 */

	/**
	 * The column contains children to display
	 * @default 'children'
	 * @type string | string[]
	 */
	childrenColumnName?: string;

	/**
	 * Override default table elements
	 * @type object
	 */
	components?: object;

	/**
	 * Expand all rows initially
	 * @default false
	 * @type boolean
	 */
	defaultExpandAllRows?: boolean;

	/**
	 * Initial expanded row keys
	 * @type string[]
	 */
	defaultExpandedRowKeys?: string[];

	/**
	 * Current expanded row keys
	 * @type string[]
	 */
	expandedRowKeys?: string[];

	/**
	 * Expanded container render for each row
	 * @type Function
	 */
	expandedRowRender?: (record?: ExpandedRowRenderRecord<T>) => VNodeChild | JSX.Element;

	/**
	 * Customize row expand Icon.
	 * @type Function | VNodeChild
	 */
	expandIcon?: Function | VNodeChild | JSX.Element;

	/**
	 * Whether to expand row by clicking anywhere in the whole row
	 * @default false
	 * @type boolean
	 */
	expandRowByClick?: boolean;

	/**
	 * The index of `expandIcon` which column will be inserted when `expandIconAsCell` is false. default 0
	 */
	expandIconColumnIndex?: number;

	/**
	 * Table footer renderer
	 * @type Function | VNodeChild
	 */
	footer?: Function | VNodeChild | JSX.Element;

	/**
	 * Indent size in pixels of tree data
	 * @default 15
	 * @type number
	 */
	indentSize?: number;

	/**
	 * i18n text including filter, sort, empty text, etc
	 * @default { filterConfirm: 'Ok', filterReset: 'Reset', emptyText: 'No Data' }
	 * @type object
	 */
	locale?: object;

	/**
	 * Row's className
	 * @type Function
	 */
	rowClassName?: (record: TableCustomRecord<T>, index: number) => string;

	/**
	 * Row selection config
	 * @type object
	 */
	rowSelection?: TableRowSelection;

	/**
	 * Set horizontal or vertical scrolling, can also be used to specify the width and height of the scroll area.
	 * It is recommended to set a number for x, if you want to set it to true,
	 * you need to add style .ant-table td { white-space: nowrap; }.
	 * @type object
	 */
	scroll?: { x?: number | true; y?: number };

	/**
	 * Whether to show table header
	 * @default true
	 * @type boolean
	 */
	showHeader?: boolean;

	/**
	 * Size of table
	 * @default 'default'
	 * @type string
	 */
	size?: SizeType;

	/**
	 * Table title renderer
	 * @type Function | ScopedSlot
	 */
	title?: VNodeChild | JSX.Element | string | ((data: Recordable) => string);

	/**
	 * Set props on per header row
	 * @type Function
	 */
	customHeaderRow?: (column: ColumnProps, index: number) => object;

	/**
	 * Set props on per row
	 * @type Function
	 */
	customRow?: (record: T, index: number) => object;

	/**
	 * `table-layout` attribute of table element
	 * `fixed` when header/columns are fixed, or using `column.ellipsis`
	 *
	 * @see https://developer.mozilla.org/en-US/docs/Web/CSS/table-layout
	 * @version 1.5.0
	 */
	tableLayout?: 'auto' | 'fixed' | string;

	/**
	 * the render container of dropdowns in table
	 * @param triggerNode
	 * @version 1.5.0
	 */
	getPopupContainer?: (triggerNode?: HTMLElement) => HTMLElement;

	/**
	 * Data can be changed again before rendering.
	 * The default configuration of general user empty data.
	 * You can configured globally through [ConfigProvider](https://antdv.com/components/config-provider-cn/)
	 *
	 * @version 1.5.4
	 */
	transformCellText?: Function;

	/**
	 * Callback executed before editable cell submit value, not for row-editor
	 *
	 * The cell will not submit data while callback return false
	 */
	beforeEditSubmit?: (data: { record: Recordable; index: number; key: string | number; value: any }) => Promise<any>;

	/**
	 * Callback executed when pagination, filters or sorter is changed
	 * @param pagination
	 * @param filters
	 * @param sorter
	 * @param currentDataSource
	 */
	onChange?: (pagination: any, filters: any, sorter: any, extra: any) => void;

	/**
	 * Callback executed when the row expand icon is clicked
	 *
	 * @param expanded
	 * @param record
	 */
	onExpand?: (expande: boolean, record: T) => void;

	/**
	 * Callback executed when the expanded rows change
	 * @param expandedRows
	 */
	onExpandedRowsChange?: (expandedRows: string[] | number[]) => void;

	onColumnsChange?: (data: ColumnChangeParam[]) => void;
}

export type ColumnChangeParam = {
	dataIndex: string;
	fixed: boolean | 'left' | 'right' | undefined;
	visible: boolean;
};
